import {
  BulgeCurveParam,
  PointArr2,
  PointArr3,
  PointObj2,
  PointObj3,
  StartEndPoint,
} from '@/types';
import { Vector2 } from 'three';

type Point2 = {
  x: number;
  y: number;
};

/** 获取向量 */
function getVector2(point2: Point2) {
  return new Vector2(point2.x, point2.y);
}
/** 批量获取向量 */
function getVector2s(Point2s: Point2[]) {
  const vecs = Point2s.map((n) => new Vector2(n.x, n.y));
  return vecs;
}
/** 获取指定向量的垂直向量 */
export function getPerpVector(vec: Vector2) {
  const { x, y } = vec;
  const perp = new Vector2(-y, x);
  perp.normalize();
  return perp;
}
/** 获取圆弧圆心 */
export function getArcCenter(
  p1: Point2,
  p2: Point2,
  radius: number,
  isMinorArc: boolean,
  isCCW: boolean,
) {
  const { pow, sqrt } = Math;
  const [p1v, p2v] = getVector2s([p1, p2]);
  const dist = p1v.distanceTo(p2v);
  const len = sqrt(pow(radius, 2) - pow(dist / 2, 2));
  const midv = p1v.clone().add(p2v).divideScalar(2);
  const perpv = getPerpVector(p2v.clone().sub(p1v));
  if ((isMinorArc && !isCCW) || (!isMinorArc && isCCW)) {
    perpv.negate();
  }
  const center = midv.clone().add(perpv.multiplyScalar(len));
  const { x, y } = center;
  return { x, y };
}
/** 获取圆弧的开始和结束角（弧度） */
export function getArc2Angle(center: Point2, p1: Point2, p2: Point2) {
  const [p1v, p2v] = getVector2s([p1, p2]);
  const centerV = getVector2(center);
  // debugger
  const startAngle = p1v.clone().sub(centerV).angle();
  const endAngle = p2v.clone().sub(centerV).angle();
  return [startAngle, endAngle];
}
/** 获取椭圆弧的开始和结束角（弧度） */
export function getEllArc2Angle(
  p1: Point2,
  p2: Point2,
  isCCW: boolean,
  curve2d: any,
) {
  const { ccs2d: ccs, a, b } = curve2d;
  ccs.dy = getPerpVector(getVector2(ccs.dx));
  let [startAngle, endAngle] = [p1, p2].map((p) => {
    const pv = getVector2(p);
    const vec = pv.sub(getVector2(ccs.o));
    const x = vec.dot(getVector2(ccs.dx)) / a;
    const y = vec.dot(getVector2(ccs.dy)) / b;
    let t = Math.atan2(y, x);
    if (t < 0) {
      t += 2 * Math.PI;
    }
    return t;
  });
  var clockSign = isCCW ? 1 : -1;
  if (clockSign < 0) {
    startAngle = Math.PI * 2 - startAngle;
    endAngle = Math.PI * 2 - endAngle;
    return [startAngle, endAngle];
  }
  return [startAngle, endAngle];
}
/** 从凸度值中获取圆弧半径  */
export function getArcRadiusByBulge(
  startPoint: Point2,
  endPoint: Point2,
  bulge: number,
) {
  // 计算顶点角度
  const angle = Math.atan(bulge) * 2;
  const startVector2 = new Vector2(startPoint.x, startPoint.y);
  const endVector2 = new Vector2(endPoint.x, endPoint.y);
  // 两点之间的距离
  const distance = startVector2.distanceTo(endVector2);
  // 根据正玄值反推
  const radius = distance / 2 / Math.sin(angle);
  return Math.abs(radius);
}
/** 从凸度值中获取圆弧 */
export function getArcByBulge(
  startPoint: Point2,
  endPoint: Point2,
  bulge: number,
) {
  const radius = getArcRadiusByBulge(startPoint, endPoint, bulge);
  const isMinorArc = Math.abs(bulge) < 1;
  const isCCW = bulge > 0;
  const center = getArcCenter(startPoint, endPoint, radius, isMinorArc, isCCW);
  const startVector2 = new Vector2(startPoint.x, startPoint.y).sub(
    new Vector2(center.x, center.y),
  );
  const startAngle = Math.atan2(startVector2.y, startVector2.x);
  const halfAngle = Math.atan(bulge) * 2;
  const endAngle = startAngle + halfAngle * 2;
  return { center, radius, startAngle, endAngle, isCCW: startAngle < endAngle };
}
/** 通过两点和圆心获取凸度 */
export function getBulgeByStartEndAndCenter({
  startPoint,
  endPoint,
  center,
  isCCW,
}: StartEndPoint & { center: PointObj2; isCCW: boolean }) {
  const [startAngle, endAngle] = getArc2Angle(center, startPoint, endPoint);
  let angle = startAngle - endAngle;
  if ((isCCW && angle > 0) || (!isCCW && angle < 0)) {
    angle = Math.abs(Math.PI - Math.abs(angle));
  }
  const sign = isCCW ? 1 : -1;
  const bulge = sign * Math.abs(Math.tan(angle / 4));
  return bulge;
}
